home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / mac / Technical Documentation / Develop / develop Issue 23 / develop Issue 23 code / Multipane Dialogs Code.sea / Multipane Dialogs Code / MPDialogs.h / MPDialogs.h
Encoding:
C/C++ Source or Header  |  1995-10-15  |  16.9 KB  |  501 lines  |  [TEXT/MMCC]

  1. /* Multi-Pane Dialog (MPD)
  2.  * By Norman Franke
  3.  */
  4.  
  5. #pragma once
  6.  
  7. /********************************************************************************
  8.  *
  9.  * Multi-Pane Dialog Constants
  10.  *
  11.  ********************************************************************************/
  12.  
  13. // Return codes
  14. #define kNotHandled        0
  15. #define kHandled        -1
  16. #define keNullData        1
  17. #define keBadPane        2
  18. #define keBadItem        3
  19. #define keWrongSize        4
  20.  
  21. // Result codes from DoMPDialogEvent
  22. #define kNotClosed        0
  23. #define kOKClosed        1
  24. #define kCancelClosed    2
  25.  
  26. // Standard item numbers in dialogs.
  27. #define kBOk            1
  28. #define kBCancel        2
  29. #define kBRevert        3
  30. #define kBFactory        4
  31. #define kIconBox        5
  32. #define kKeyStrings        6
  33. #define kLine            7
  34.  
  35. // Action messages for use in the various Action Procedures.
  36. #define kR2TAction        0
  37. #define kP2TAction        1
  38. #define kT2PAction        2
  39. #define kT2RAction        3
  40. #define kCalcAction        4
  41. #define kInitAction        5
  42. #define kClickAction    6
  43. #define kValidateAction    7
  44.  
  45. // Types of Action Procedures used in InstallAction and RemoveAction.
  46. #define kItemAction        1
  47. #define kEditAction        2
  48. #define kGroupAction    3
  49. #define kDefAction        4
  50.  
  51. // Arrow Keys on the keyboard.
  52. #define kLeftArrow        0x1c
  53. #define kRightArrow        0x1d
  54. #define kUpArrow        0x1e
  55. #define kDownArrow        0x1f
  56.  
  57. // Special resource types used here.
  58. #define kDTL            'DTL#'
  59. #define kGROUP            'DGRP'
  60.  
  61. // Resources for the List pseudo-CDEF.
  62. #define rIconDef        130
  63.  
  64. /********************************************************************************
  65.  *
  66.  * Multi-Pane Dialog Data Types and Universal Procedure Pointers
  67.  *
  68.  ********************************************************************************/
  69.  
  70. // Radio Group linked list.
  71. typedef struct RadioGroup {
  72.     struct RadioGroup *next;
  73.     short pane;
  74.     short num;
  75.     short items[1];
  76. } RadioGroup, *RadioGroupPtr;
  77.  
  78. #if USESROUTINEDESCRIPTORS
  79. #define kCallConvention kPascalStackBased
  80. #endif
  81.  
  82. // Types for the Action procedures.
  83. typedef short ClickActionProc(short, DialogPtr, short, short);
  84. typedef ClickActionProc *ClickActionPtr;
  85.  
  86. #if USESROUTINEDESCRIPTORS
  87. enum {
  88.     kClickProcInfo = kCallConvention |
  89.         STACK_ROUTINE_PARAMETER(1, sizeof(short)) |
  90.         STACK_ROUTINE_PARAMETER(2, sizeof(DialogPtr)) |
  91.         STACK_ROUTINE_PARAMETER(3, sizeof(short)) |
  92.         STACK_ROUTINE_PARAMETER(4, sizeof(short)) |
  93.         RESULT_SIZE(sizeof(short))
  94. };
  95.  
  96. typedef UniversalProcPtr ClickActionUPP;
  97.  
  98. #define CallClickActionProc(userRoutine, a1, a2, a3, a4)        \
  99.         CallUniversalProc((UniversalProcPtr)(userRoutine), kClickProcInfo, a1, a2, a3, a4)
  100. #define NewClickActionProc(userRoutine)        \
  101.         (ClickActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kClickProcInfo, GetCurrentISA())
  102. #else
  103. typedef ClickActionPtr ClickActionUPP;
  104.  
  105. #define CallClickActionProc(userRoutine, a1, a2, a3, a4) \
  106.         (*(userRoutine))(a1, a2, a3, a4)
  107. #define NewClickActionProc(userRoutine) (ClickActionUPP)(userRoutine)
  108. #endif
  109.  
  110. typedef short EditActionProc(short, Ptr, Handle, short, short);
  111. typedef EditActionProc *EditActionPtr;
  112.  
  113. #if USESROUTINEDESCRIPTORS
  114. enum {
  115.     kEditProcInfo = kCallConvention |
  116.         STACK_ROUTINE_PARAMETER(1, sizeof(short)) |
  117.         STACK_ROUTINE_PARAMETER(2, sizeof(Ptr)) |
  118.         STACK_ROUTINE_PARAMETER(3, sizeof(Handle)) |
  119.         STACK_ROUTINE_PARAMETER(4, sizeof(short)) |
  120.         STACK_ROUTINE_PARAMETER(5, sizeof(short)) |
  121.         RESULT_SIZE(sizeof(short))
  122. };
  123.  
  124. typedef UniversalProcPtr EditActionUPP;
  125.  
  126. #define CallEditActionProc(userRoutine, a1, a2, a3, a4, a5)        \
  127.         CallUniversalProc((UniversalProcPtr)(userRoutine), kEditProcInfo, a1, a2, a3, a4, a5)
  128. #define NewEditActionProc(userRoutine)        \
  129.         (EditActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kEditProcInfo, GetCurrentISA())
  130. #else
  131. typedef EditActionPtr EditActionUPP;
  132.  
  133. #define CallEditActionProc(userRoutine, a1, a2, a3, a4, a5) \
  134.         (*(userRoutine))(a1, a2, a3, a4, a5)
  135. #define NewEditActionProc(userRoutine) (EditActionUPP)(userRoutine)
  136. #endif
  137.  
  138. typedef short GroupActionProc(short, RadioGroupPtr, Handle, DialogPtr, Ptr, short, short);
  139. typedef GroupActionProc *GroupActionPtr;
  140.  
  141. #if USESROUTINEDESCRIPTORS
  142. enum {
  143.     kGroupProcInfo = kCallConvention |
  144.         STACK_ROUTINE_PARAMETER(1, sizeof(short)) |
  145.         STACK_ROUTINE_PARAMETER(2, sizeof(RadioGroupPtr)) |
  146.         STACK_ROUTINE_PARAMETER(3, sizeof(Handle)) |
  147.         STACK_ROUTINE_PARAMETER(4, sizeof(DialogPtr)) |
  148.         STACK_ROUTINE_PARAMETER(5, sizeof(Ptr)) |
  149.         STACK_ROUTINE_PARAMETER(6, sizeof(short)) |
  150.         STACK_ROUTINE_PARAMETER(7, sizeof(short)) |
  151.         RESULT_SIZE(sizeof(short))
  152. };
  153.  
  154. typedef UniversalProcPtr GroupActionUPP;
  155.  
  156. #define CallGroupActionProc(userRoutine, a1, a2, a3, a4, a5, a6, a7)        \
  157.         CallUniversalProc((UniversalProcPtr)(userRoutine), kGroupProcInfo, a1, a2, a3, a4, a5, a6, a7)
  158. #define NewGroupActionProc(userRoutine)        \
  159.         (GroupActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kGroupProcInfo, GetCurrentISA())
  160. #else
  161. typedef GroupActionPtr GroupActionUPP;
  162.  
  163. #define CallGroupActionProc(userRoutine, a1, a2, a3, a4, a5, a6, a7) \
  164.         (*(userRoutine))(a1, a2, a3, a4, a5, a6, a7)
  165. #define NewGroupActionProc(userRoutine) (GroupActionUPP)(userRoutine)
  166. #endif
  167.  
  168. typedef void DefActionProc(Ptr, short, short, short, short);
  169. typedef DefActionProc *DefActionPtr;
  170.  
  171. #if USESROUTINEDESCRIPTORS
  172. enum {
  173.     kDefProcInfo = kCallConvention |
  174.         STACK_ROUTINE_PARAMETER(1, sizeof(Ptr)) |
  175.         STACK_ROUTINE_PARAMETER(2, sizeof(short)) |
  176.         STACK_ROUTINE_PARAMETER(3, sizeof(short)) |
  177.         STACK_ROUTINE_PARAMETER(4, sizeof(short)) |
  178.         STACK_ROUTINE_PARAMETER(5, sizeof(short))
  179. };
  180.  
  181. typedef UniversalProcPtr DefActionUPP;
  182.  
  183. #define CallDefActionProc(userRoutine, a1, a2, a3, a4, a5)        \
  184.         CallUniversalProc((UniversalProcPtr)(userRoutine), kDefProcInfo, a1, a2, a3, a4, a5)
  185. #define NewDefActionProc(userRoutine)        \
  186.         (DefActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kDefProcInfo, GetCurrentISA())
  187. #else
  188. typedef DefActionPtr DefActionUPP;
  189.  
  190. #define CallDefActionProc(userRoutine, a1, a2, a3, a4, a5) (*(userRoutine))(a1, a2, a3, a4, a5)
  191. #define NewDefActionProc(userRoutine) (DefActionUPP)(userRoutine)
  192. #endif
  193.  
  194. // All the state used by the multi-pane dialog code.
  195. typedef struct MPDRec {
  196.     // Number of panes in the dialog
  197.     short            numPanes;
  198.     // Current pane being displayed
  199.     short            currentPane;
  200.     // Item number of first item in the panes
  201.     short            baseItems;
  202.     // List of IDs for the pane's DITLs
  203.     short            *paneIDs;
  204.     // Whether the Revert button should be enabled
  205.     short            paneDirty;
  206.     // Linked list of Radio Groups
  207.     RadioGroupPtr    radio;
  208.     // Actual and temporary storage for dialog values
  209.     Handle            theData, tmpData;
  210.     // List of icon suites
  211.     Handle            *IconHandles;
  212.     // List Manager list for the icon list
  213.     ListHandle        theList;
  214.     // Action Procedures
  215.     ClickActionUPP    ClickAction;
  216.     EditActionUPP    EditAction;
  217.     GroupActionUPP    GroupAction;
  218.     DefActionUPP    DefAction;
  219. } MPDRec, *MPDPtr, **MPDHdl;
  220.  
  221. /********************************************************************************
  222.  *
  223.  * Main Multi-Pane Dialog Routines
  224.  *
  225.  ********************************************************************************/
  226.  
  227. /* Open a new MPD.
  228.  *
  229.  * First parameter is the resource ID of the DLOG and DTL# for the dialog.
  230.  *   DTL#'s list the name and ID for each pane.
  231.  *   The ID is also for the icon group and optional DGRP resource.
  232.  * Second through fifth parameters allow custom procedure for handling:
  233.  *   - Code to set factory defaults,
  234.  *   - Actions when items are clicked on,
  235.  *   - How TextEdit fields are treated, and
  236.  *   - How Radio Groups are handled.
  237.  * Last parameter is the storage for the MPD data.
  238.  *   Passing a pointer to NULL will create a new one based on the DITLs.
  239.  */
  240. DialogPtr OpenMPDialog(short resID, DefActionUPP defAction, ClickActionUPP clickProc,
  241.     EditActionUPP editAction, GroupActionUPP groupAction, Handle *theData);
  242.  
  243. /* Return the MPD storage handle without opening the dialog.
  244.  *
  245.  * First parameter is the resource ID of the DLOG and DTL# for the dialog.
  246.  * Second and third parameters are the Edit and Group action procedures that will be
  247.  *   used with calls to OpenMPDialog above.
  248.  */
  249. Handle GetMPDialogHandle(short resID, EditActionUPP editAction, GroupActionUPP groupAction);
  250.  
  251. /* Remove a MPD,
  252. *    and deallocates all storage, exept the data handle.
  253.  */
  254. void CloseMPDialog(DialogPtr *dlog);
  255.  
  256. /* Handle an event in the MPD.
  257.  *
  258.  * Returns kNotHandled if the event is not for the MPD.
  259.  * The DialogPtr is set to NULL if the event caused the MPD to close.
  260.  *   (CloseMPDialog is called in this case.)
  261.  */
  262. short DoMPDialogEvent(DialogPtr *dlog, EventRecord *theEvent, short *result);
  263.  
  264. /* Count the number of edit fields in the current pane.
  265.  */
  266. short NumberOfEditFields(DialogPtr dlog);
  267.  
  268. /* Determine if the current pane has more than a single edit field.
  269.  * Returns true if so.
  270.  */
  271. Boolean MultipleEditFields(DialogPtr dlog);
  272.  
  273. /* Installs an Action Procedure.
  274.  *
  275.  * First parameter is the type, second is the DialogPtr of the MPD,
  276.  *   third is the ProcPtr to the Action procedure.
  277.  * If NULL is passed for the ProcPtr, the Action procedure is reset to
  278.  *   the default action.
  279.  */
  280. short InstallAction(short aType, DialogPtr dlog, UniversalProcPtr actionProc);
  281.  
  282. /* Remove an Action Procedure.
  283.  *
  284.  * Calls InstallAction with a NULL actionProc.
  285.  */
  286. short RemoveAction(short aType, DialogPtr dlog);
  287.  
  288. /********************************************************************************
  289.  *
  290.  * Multi-Pane Dialog Data Access Routines
  291.  *
  292.  ********************************************************************************/
  293.  
  294. /* Retrieve a MPD item value.
  295.  *
  296.  * Given a MPD data handle, pane ID and item it will retrieve the
  297.  *   data into the passed pointer.
  298.  * It verifies that the length is correct, and a valid pane and item were passed.
  299.  */
  300. short GetMPDItem(Handle theData, short pane, short item, Ptr ptr, short len);
  301.  
  302. /* Store a MPD item value.
  303.  *
  304.  * Given a MPD data handle, pane ID and item it will store the
  305.  *   data from the passed pointer into the MPD data handle.
  306.  * It verifies that the length is correct, and a valid pane and item were passed.
  307.  */
  308. short SetMPDItem(Handle theData, short pane, short item, Ptr ptr, short len);
  309.  
  310. /********************************************************************************
  311.  *
  312.  * Internal Multi-Pane Dialog Routines
  313.  *
  314.  ********************************************************************************/
  315.  
  316. /* Display a pane.
  317.  *
  318.  * Removes the old pane and installes the new in the dialog.
  319.  */
  320. void InstallDITL(DialogPtr dlog, short pane);
  321.  
  322. /* Create a new empty MPD data handle.
  323.  *
  324.  * The first part of the handle is a series of long offsets into
  325.  *   the handle where the individual pane values are stored, zero terminated.
  326.  * Controls, Check boxes and non-groups Radio Buttons are stored as shorts.
  327.  * Default action is to store TextEdit fields as Str255's.
  328.  * A single short is allocated for a Radio Group.
  329.  * The end of the item list per pane is zero terminated.
  330.  */
  331. Handle MPDTemplateFromDITL(MPDHdl dataH);
  332.  
  333. /* Create a Radio Group.
  334.  *
  335.  * First parameter is the MPD, second is the pane ID,
  336.  *  third is a list of item numbers for the group (numbering local to the DITL),
  337.  *  last is the number of items in the array/group.
  338.  */
  339. short CreateMPDRadioGroup(DialogPtr dlog, short pane, short *itemList, short itemNum);
  340.  
  341. /* Create Radio Groups for a pane.
  342.  *
  343.  * First parameter is the MPD, second is the pane ID.
  344.  * This reads a DGRP resource to get the Radio Groups for a pane.
  345.  * Most of the work is done in CreateMPDRadioGroup.
  346.  */
  347. void CreateRadioGroups(DialogPtr dlog, short pane);
  348.  
  349. /* Sets MPD controls on the display to their factory settings.
  350.  *
  351.  * Given the MPD and the pane, it sets the default values for the controls on that pane.
  352.  */
  353. void SetFactoryDefault(DialogPtr dlog, short pane);
  354.  
  355. /* Toggle items in a Radio Group.
  356.  *
  357.  * Given the MPD, the specific Radio and a DITL-local number,
  358.  *   make sure it's the only Radio Button set in the group.
  359.  */
  360. void ToggleGroup(DialogPtr dlog, RadioGroupPtr group, short item);
  361.  
  362. /* Calculates the size the Radio Button needs in the MPD data handle.
  363.  *
  364.  * If the radio button is a member of a Radio Group it returns zero,
  365.  *   since radio groups are stored separately.
  366.  * Otherwise it returns sizeof(short).
  367.  * It is passed the first Radio Group and the pane and item of the control.
  368.  */
  369. short GetRadioMPDSize(RadioGroupPtr radio, short pane, short item);
  370.  
  371. /********************************************************************************
  372.  *
  373.  * Internal Multi-Pane Dialog Action Procedures
  374.  *
  375.  ********************************************************************************/
  376.  
  377. /* MPD Action Procedure.
  378.  *
  379.  * Given the MPD and pane, and
  380.  * depending on the value of the second argument it will:
  381.  *   - Create a working copy of the MPD data handle for use,
  382.  *   - Call P2TMPDAction to save the controls,
  383.  *   - Call T2PMPDAction to set the controls,
  384.  *   - Save the temporary results of the MPD into the MPD data handle,
  385.  *   - Call P2TMPDAction or T2PMPDAction.
  386.  */
  387. short HandleMPDAction(DialogPtr dlog, short message, short pane);
  388.  
  389. /* Transfer the MPD controls as displayed into the temporary MPD data handle.
  390.  *
  391.  * When the user switches panes, the values need to be saved.
  392.  * It calls the Action Procedure for Radio Button and TextEdit fields.
  393.  * If a radio button is not in a group, it is treated like a check box.
  394.  */
  395. short P2TMPDAction(DialogPtr dlog, short pane);
  396.  
  397. /* Transfer the values from the temporary MPD data handle to the display.
  398.  *
  399.  * When the user switches panes, the values need to be restored.
  400.  * It calls the Action Procedure for Radio Button and TextEdit fields.
  401.  * If a radio button is not in a group, it is treated like a check box.
  402.  */
  403. short T2PMPDAction(DialogPtr dlog, short pane);
  404.  
  405. /* Handler for when a user clicks on a Radio Button.
  406.  *
  407.  * Returns kNotHandled if the radio button is not in a Radio Group.
  408.  * It gets passed the MPD and the DITL local item number hit.
  409.  */
  410. short HandleRadioGroup(DialogPtr dlog, short item);
  411.  
  412. /* Do Radio Group Action Procedure.
  413.  *
  414.  * Calls the Group Action Procedure for each Radio Group.
  415.  * For kP2TAction and kT2PAction dlog is the MPD,
  416.  *   for kCalcAction and kInitAction it is the MPDHdl.
  417.  */
  418. short DoGroupAction(short mType, DialogPtr dlog, Ptr hPtr, short pane, short *item);
  419.  
  420. /********************************************************************************
  421.  *
  422.  * Default Action Procedures
  423.  *
  424.  ********************************************************************************/
  425.  
  426. /* Set default values for a pane.
  427.  *
  428.  * Given the data pointer, length of item's storage, type, pane and DITL local item,
  429.  *   set the defaults for all the items on that pane.
  430.  * Default action sets everything to zero.
  431.  */
  432. void DefaultAction(Ptr theData, short len, short iType, short pane, short item);
  433.  
  434. /* TextEdit Action Procedure.
  435.  *
  436.  * Depending on the value of the first argument it will:
  437.  *   - Save the value of a TextEdit field, which is the actual text as a pascal string.
  438.  *   - Set the value of a TextEdit field.
  439.  *   - Return the amount of item storage needed for a TextEdit (256).
  440.  *   - Initialize the TextEdit record.
  441.  * Second parameter is the ControlHandle for the control being processed,
  442.  *   followed by the pane and item number of the control.
  443.  */
  444. short DefaultEditAction(short mType, Ptr hPtr, Handle iHandle, short pane, short item);
  445.  
  446. /* Action Procedure when something is clicked or validated.
  447.  *
  448.  * The first parameter specifies the message type:
  449.  *   kInitAction, kValidateAction or kClickAction
  450.  * For clicking and initialization:
  451.  *   Nothing happens for buttons and controls,
  452.  *   Radio groups are handled in HandleRadioGroup or are toggled if it can't, and
  453.  *   Check boxes are simply toggled.
  454.  * Validation always succeeds.
  455.  */
  456. short DefaultClickAction(short mType, DialogPtr dlog, short pane, short item);
  457.  
  458. /* Radio Group Action Procedure.
  459.  *
  460.  * Depending on the value of the first argument it will:
  461.  *   - Save the value of a Radio Group, which is the index of the control in the group.
  462.  *   - Set the value of a Radio Group.
  463.  *   - Return the amount of item storage needed for a Radio Group.
  464.  *   - Initialize the value of the Radio Group to 1.
  465.  * The second argument is the Radio Group being processed, third is the MPDHdl,
  466.  *   fourth the DialogPtr, fifth a pointer to the storage pointer (which is updated
  467.  *   here), lastly the pane and item number of the control in the group.
  468.  */
  469. short DefaultGroupAction(short mType, RadioGroupPtr group, Handle H, DialogPtr dlog,
  470.     Ptr hPtr, short pane, short item);
  471.  
  472.  
  473. /* Useful routines I use a lot.
  474.  * By Norman Franke
  475.  */
  476.  
  477. // ******************** Gray Line
  478. pascal void DrawGray (DialogPtr theDialog, short theItem);
  479. void SetItemToGray(DialogPtr dlog, short item);
  480.  
  481. // ******************** Command Key Equivalents
  482. pascal Boolean keyAltFilter(DialogPtr dlg, short theItem, short offset, EventRecord *event, short *item);
  483.  
  484. // ******************** Menu
  485. void AbleDisItem(short menu, short item, short flag);
  486.  
  487. // ******************** Grow Icon
  488. void MyDrawGrow(WindowPtr win);
  489.  
  490. // ******************** Dialog & Window
  491. void HiliteItem(DialogPtr dlgPtr, short itemNo, short state);
  492. ControlHandle GetItemHandle(DialogPtr theDialog, short item);
  493. short GetDItemValue(DialogPtr dlgPtr, short itemNo);
  494. void AbleDItem(DialogPtr dlog, short item, short state);
  495. short GetDialogItemValue(DialogPtr dlgPtr, short itemNo);
  496. DialogPtr MyGetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow,
  497.     WindowPtr behind, Boolean *wasVisible);
  498.  
  499. // ******************** Miscelaneous
  500. void Pstrcpy(Str255, ConstStr255Param);
  501.